package com.bruce.starts.demo.commonerror.cachedesign;

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;

/**
 * @author luotuan
 * @Description
 * @create 2021-05-13 21:33
 **/
@Slf4j
@RestController
@RequestMapping("cachepenetration")
public class CachePenetrationController {
    @Autowired
    private StringRedisTemplate redisTemplate;
    private AtomicInteger atomicInteger = new AtomicInteger();
    private BloomFilter<Integer> bloomFilter;
    @PostConstruct
    public void init() {
//        IntStream.rangeClosed(1, 1000).forEach(i -> {
//            redisTemplate.opsForValue().set("data" + i, getStrFromDb(i), 30, TimeUnit.SECONDS);
//        });
        bloomFilter = BloomFilter.create(Funnels.integerFunnel(),10000,0.01);
        IntStream.rangeClosed(1,10000).forEach(bloomFilter::put);
    }

    //@Scheduled(fixedRate = 1000)
    private void metrics() {
        log.info("DB QPS: {}", atomicInteger.getAndSet(0));
    }

    @GetMapping("getData")
    public String getData(@RequestParam int id) {
        String data = redisTemplate.opsForValue().get("data" + id);
        if (StringUtils.isEmpty(data)) {
            if(bloomFilter.mightContain(id)){
                data = getStrFromDb(id);
                redisTemplate.opsForValue().set("data" + id, data, 30, TimeUnit.SECONDS);
            }
        }
        return data;
    }

    private String getStrFromDb(int id) {
        atomicInteger.incrementAndGet();
        if (id > 0 && id <= 10000){
            return "test" + id + System.currentTimeMillis();
        }
        return "";
    }
}
